package com.lesama.stonepuzzle;

import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

public class MainFrame extends JFrame implements KeyListener {
    static int[][] data = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 0}
    };

    static int[][] win = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 0}
    };

    static int count = 0; // 记录步数

    int row; // 记录0号元素的行坐标
    int col; // 记录0号元素的纵坐标

    public MainFrame() {
        // 为窗体创建键盘监听事件
        // 将MainFrame类作为KeyListener的实现类，这样就可以传入this对象来注册监听事件
        this.addKeyListener(this);
        initFrame(); // 创建窗体
        initData();
        paintView(); // 绘制界面
        setVisible(true); // 设置窗体可见
    }


    /**
     * 重新开始游戏
     * */
    public void restart() {
        initData();
        paintView();
        count = 0; // 步数清0
    }


    /**
    * 用于初始化窗体
    * */
    public void initFrame() {
        setTitle("石头迷阵单机版v1.0");
        setLayout(null);
        setSize(514, 585);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setAlwaysOnTop(true); // 设置窗体始终置顶
        setLocationRelativeTo(null); // 设置窗体位置居中

    }

    /**
     * 初始化数组数据
     * */
    public void initData() {
        Random r = new Random();
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                int randomX = r.nextInt(4);
                int randomY = r.nextInt(4);
                int temp = data[i][j];
                data[i][j] = data[randomX][randomY];
                data[randomX][randomY] = temp;
            }
        }
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                if(0 == data[i][j]) {
                    row = i;
                    col = j;
                }
            }
        }
    }

    /**
     * 用于绘制界面
     * */
    public void paintView() {
        getContentPane().removeAll(); // 每次绘制前先移除面板中的元素

        // 设置重新开始按钮
        JButton button = new JButton("重新开始");
        button.addActionListener(e -> restart());
        button.setBounds(350, 0, 100, 40);
        button.setFocusable(false); // 取消聚焦
        getContentPane().add(button);

        // 展示已经移动的步数
        JLabel labelCount = new JLabel("步数：" + count);
        labelCount.setBounds(0, 0, 100, 50);
        getContentPane().add(labelCount);

        if (victory()) {
            JLabel labelWin = new JLabel(new ImageIcon("D:\\project\\java-learning\\java-advanced-codes\\day04\\image\\win.png"));
            labelWin.setBounds(124, 230, 266, 88);
            getContentPane().add(labelWin);
        }

        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                JLabel label = new JLabel(new ImageIcon("D:\\project\\java-learning\\java-advanced-codes\\day04\\image\\" + data[i][j] + ".png"));
                label.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
                getContentPane().add(label);
            }
        }

        JLabel labelBg = new JLabel(new ImageIcon("D:\\project\\java-learning\\java-advanced-codes\\day04\\image\\background.png"));
        labelBg.setBounds(26, 30, 450, 484);
        getContentPane().add(labelBg);
        getContentPane().repaint(); // 绘制完后再让面板重新刷新
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        move(keyCode);
        paintView();
    }

    /**
     * 移动逻辑
     * */
    private void move(int keyCode) {
        if (victory())  return; // 游戏胜利则不再允许移动
        if(keyCode == 37) {
            if (col == 3)   return; // 避免越界
            swap(data, row, col, row, ++col);
        } else if(keyCode == 38) {
            if (row == 3)   return;
            swap(data, row, col, ++row, col);
        } else if(keyCode == 39) {
            if (col == 0)   return;
            swap(data, row, col, row, --col);
        } else if(keyCode == 40) {
            if (row == 0)   return;
            swap(data, row, col, --row, col);
        } else if(keyCode == 90) {
            data = new int[][]{
                    {1, 2, 3, 4},
                    {5, 6, 7, 8},
                    {9, 10, 11, 12},
                    {13, 14, 15, 0}
            };
            row = 3;
            col = 3;
        }
        count++;
    }

    /**
     * 判断游戏是否胜利
     * */
    public boolean victory() {
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                if (data[i][j] != win[i][j])
                    return false;
            }
        }
        return true;
    }

    private void swap(int[][] arr, int i, int j, int x, int y) {
        int temp = arr[i][j];
        arr[i][j] = arr[x][y];
        arr[x][y] = temp;
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }
}
